package rs.thread;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/* Classe responsabile della creazione e gestione dei thread necessari per un certo task.
 * Vengono creati un numero di thread pari al numero di processori disponibili.
 * La classe è parametrica rispetto alla lista di oggetti di tipo T che dovrà essere processata. */
public class MultiThreadWorker<T> {
	
	/* Metodo per far si che ogni elemento della lista 'list' sia processato da 'processor' in maniera concorrente. */
	public int compute(OnerousProcessor<T> processor, List<T> list) {
		int threads = Runtime.getRuntime().availableProcessors();
		ExecutorService pool = Executors.newFixedThreadPool(threads);
		
		List<Future<Integer>> pending = new LinkedList<Future<Integer>>();
		ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<T>();
		queue.addAll(list);
		
		for (int i = 0; i < threads; i++ ) {
			pending.add(pool.submit(new WorkerTask<T>(processor, queue)));
		}
		
		int sum = 0;
		try {
			for (Future<Integer> f : pending) {
					sum += f.get();
			}
		} 
		catch (InterruptedException e) {
			e.printStackTrace();
		} 
		catch (ExecutionException e) {
			e.printStackTrace();
		}
		finally {
			pool.shutdown();
		}
		
		return sum;
	}

}
